<template>
  <view class="content">
    <view class="live-wrapper">
      <!-- 推拉流列表 -->
      <view class="containerBase">
        <live-pusher
          id="livePusher1"
          :url="livePusherUrl"
          waiting-image="https://storage.zego.im/downloads/pause_publish.png"
          v-if="isPusherShow"
          mode="SD"
          min-bitrate="800"
          max-bitrate="1500"
          @statechange="statechange"
          @netstatus="netstatus"
          @error="pusherError"
        ></live-pusher>
        <live-player
          v-for="streamItem in livePlayerList"
          :id="streamItem.streamID"
          :key="streamItem.streamID"
          :src="streamItem.url"
          autoplay
          @statechange="playStatechange"
          @netstatus="playNetstatus"
          @error="playError"
        ></live-player>
      </view>
      <!-- 混流播放列表 -->
      <view class="containerBase">
        <live-player
          v-for="streamItem in mixPlayerList"
          :id="streamItem.streamID"
          :key="streamItem.streamID"
          :src="streamItem.url"
          autoplay
          @statechange="playStatechange"
          @netstatus="playNetstatus"
          @error="playError"
        ></live-player>
      </view>
    </view>

    <view class="index-container">
      <view class="input-container">
        <input v-model="roomID" placeholder="请输入房间 ID" placeholder-style="color: #b3b3b3; font-size: 14px;" class="room-input" />
        <text class="tip"></text>
      </view>
      <view class="button-container">
        <button @click="openRoom(1)" class="util-btn">加入房间(推流)</button>
        <button @click="openRoom(0)" class="util-btn">加入房间(不推流)</button>
        <button @click="startMixStream" v-if="!hasMix" class="util-btn">开始混流</button>
        <button @click="stopMixStream" v-if="hasMix" class="util-btn">停止混流</button>

        <button @click="logout" class="util-btn">退出房间</button>
      </view>
    </view>
    <view class="settings">
      <button v-if="isSettingShow" open-type="openSetting" @openSetting="settingCallback">
        授权使用摄像头和麦克风
      </button>
    </view>
  </view>
</template>

<script>
import { CommonExpress } from "../../utils/wxmini/common"

export default {
  data() {
    return {
      commonExpress: null,
      roomID: "126",
      livePusherctx: "",
      livePusherUrl: "",
      isPusherShow: false,
      isSettingShow: false,
      livePlayerList: [],
      mixPlayerList: [],
      mixStreamID: "wxmini_mixS" + Date.now(),
      mixTaskID: "wxmini_mixT" + Date.now(),
      hasMix: false
    }
  },

  methods: {
    async openRoom(type) {
      // 0 不推流 1 推流
      await this.commonExpress.login(this.roomID)
      if (type === 1) {
        // 获取到推流地址 推流流地址
        const { url } = await this.commonExpress.getPublishStream()
        this.livePusherUrl = url
        this.isPusherShow = true
        this.$nextTick(async () => {
          // // 创建 pusher上下文 ， 一般建议在需要推流的时候，再创建上下文，以及 stateChange监听 和 netChange 监听
          this.livePusherctx = uni.createLivePusherContext("livePusher1", this)
          // this.livePusherctx.url = url  //注释掉试试
          //  开始推流，同时开启摄像头预览
          const res = await this.livePusherctx.start()
        })
      }
    },

    settingCallback(e) {
      console.log("mytag settingCallback e", e)
      if (e.errMsg.includes("ok")) {
        this.isSettingShow = false
      }
    },

    async logout() {
      // 停止推流
      if (this.livePusherctx && this.livePusherUrl) {
        this.commonExpress.zegoApi.stopPublishingStream(this.livePusherUrl)
        this.livePusherctx.stop()
      }

      // 停止拉流
      this.livePlayerList.forEach((item) => {
        this.commonExpress.zegoApi.stopPlayingStream(item.streamID)
      })
      this.livePlayerList = []

      // 退出房间服务
      const res = await this.commonExpress.zegoApi.logoutRoom()
      uni.navigateBack()
      console.log("mytag res", res)
    },

    async initCommon() {
      // 初始化 expressApi
      this.commonExpress = new CommonExpress()
      // 检查 摄像头和 麦克风能力
      const checkRes = await this.commonExpress.checkSystemRequirements()
      this.livePlayerList = this.commonExpress.livePlayerList // 与 commonExpress中的 livePlayerList进行深拷贝。
      if (!checkRes) this.isSettingShow = true
    },

    // 开始混流
    async startMixStream() {
      // 本端推流
      const inputList = [
        {
          streamID: this.commonExpress.streamID,
          contentType: "video",
          layout: {
            top: 0,
            left: 0,
            bottom: 480,
            right: 640
          }
        }
      ]
      // 拉流列表中的一条
      if (this.livePlayerList.length) {
        const playerStream = this.livePlayerList[0]
        inputList.push({
          streamID: playerStream.streamID,
          contentType: "video",
          layout: {
            top: 480,
            left: 0,
            bottom: 960,
            right: 640
          }
        })
      }
      const outputList = [
        {
          target: this.mixStreamID
        }
      ]

      const outputConfig = {
        outputBitrate: 800 * 1000,
        outputFPS: 15,
        outputWidth: 640,
        outputHeight: 960
      }
      const mixParam = {
        taskID: this.mixTaskID,
        inputList,
        outputList,
        outputConfig
      }
      try {
        console.log("mytag mixParam", mixParam)
        const result = await this.commonExpress.zegoApi.startMixerTask(mixParam)
        console.log("mytag result ", result)
        if (result.errorCode !== 0) return console.error("mix fail", result)
        const mixPlayRes = await this.commonExpress.zegoApi.startPlayingStream(this.mixStreamID, { isMix: true })
        console.log("mytag mixPlayRes", mixPlayRes)
        this.mixPlayerList = [mixPlayRes]
        this.hasMix = true
      } catch (error) {
        console.log("mytag mixError error", error)
      }
    },

    // 结束混流
    async stopMixStream() {
      try {
        const { errorCode } = await this.commonExpress.zegoApi.stopMixerTask(this.mixTaskID)
        if (errorCode === 0) {
          this.mixPlayerList.forEach((item) => {
            this.commonExpress.stopPlayingStream(item.streamID)
          })
          this.mixPlayerList = []
          this.hasMix = false
        }
      } catch (error) {}
    },

    // live-pusher 推流状态回调
    statechange(e) {
      console.log("mytag statechange this.commonExpress.streamID, e", this.commonExpress.streamID, e)
      try {
        if (e.detail.code === -1307) {
          uni.showToast({
            icon: "none",
            title: "网络断连，且经多次重连抢救无效，更多重试请自行重启推流"
          })
        }
        this.commonExpress.zegoApi.updatePlayerState(this.commonExpress.streamID, e)
      } catch (error) {
        console.log("mytag state ", error)
      }
    },

    // live-pusher 推流网络状态通知
    netstatus(e) {
      try {
        console.warn("mytag netstatus", this.commonExpress.streamID, e)
        this.commonExpress.zegoApi.updatePlayerNetStatus(this.commonExpress.streamID, e)
      } catch (error) {
        console.log("mytag netState ", error)
      }
    },

    // live-pusher 错误
    pusherError(e) {
      console.warn("mytag pusherError", e)
    },

    // live-player 拉流状态回调
    playStatechange(e) {
      console.log("mytag player playStatechange e", e.currentTarget.id, e)
      if (e.detail.code === -1307) {
        uni.showToast({
          icon: "none",
          title: "网络断连，且经多次重连抢救无效，更多重试请自行重启推流"
        })
      }
      this.commonExpress.zegoApi.updatePlayerState(e.currentTarget.id, e)
    },

    // live-player 拉流网络状态通知
    playNetstatus(e) {
      console.log("mytag player playNetstatus", e.currentTarget.id, e)
      this.commonExpress.zegoApi.updatePlayerNetStatus(e.currentTarget.id, e)
    },

    // live-player 错误
    playError(e) {
      console.warn("mytag player pusherError", e)
    }
  },

  async mounted() {
    this.initCommon()
  }
}
</script>

<style>
/* pages/mix/index.wxss */
.live-wrapper {
  display: flex;
}
.containerBase {
  height: 73vh;
  max-height: 500px;
  padding: 10rpx;
}

live-pusher,
live-player {
  width: 45vw;
  height: 45vw;
  max-width: 200px;
  max-height: 200px;
  margin: 5rpx;
}

.index-container {
  border-top: 1px slategrey solid;
}
.input-container {
  text-align: center;
}
.button-container {
  border-top: 1px slategrey solid;
}
.room-input {
  height: 80rpx;
  border-bottom: 1px solid rgba(13, 112, 255, 0.5);
}
.util-btn {
  display: inline-block;
  width: 48vw;
  margin: 7rpx;
  font-size: 34rpx;
}
</style>
